/**********************************************************************
 * method 方法名 对应配置语句 
 * data 参数 json 对象
 * ts 时间戳 
 * sign 签名
 * @url: /services/apexrest/rest
 * @{"data":{"method":"api_getWorkOrder","params":{"p1":"1234"}}}
*************************************************************************/
@RestResource(urlMapping='/CRM/queryDataREST')
global with sharing class QueryDataREST {
    @HttpPost
    global static RestReturnMessage doPost(QueryBean data ) {
         RestReturnMessage message = null;
        try {
            //加载配置文件
            List<StaticResource> srs = [select Body from StaticResource  where name = 'QueryDataREST' limit 1 ];
            if(srs.isEmpty()) throw new DmlException('没有找到配置文件!');
        
            Map<String,Object> apIMap =(Map<String,Object> )  JSON.deserializeUntyped(srs[0].Body.toString());
            //解析配置
            if(!apIMap.containsKey(data.method))throw new DmlException('没有找到相关接口');
            Map<String,Object> apIInfo = (Map<String,Object>)apIMap.get(data.method);

            
            List<Object> mustParams = (List<Object> )apIInfo.get('mustFill');


            Map<String,Object> param = data.params ;

            //验证参数必填
            if(mustParams != null && !mustParams.isEmpty() ){
                for (Object o  : mustParams ) {
                    if(!param.containsKey((String) o ) || String.isBlank((String) param.get((String)o)) )throw new DmlException(o + ':参数必填!');
                }
            }

            //解析参数-->重构 sql --> 获取数据 
            Object sqls = apIInfo.get('sql');
            if(sqls instanceof String ){

                String sql = (String) sqls ;
                Map<String,Object> fieldMap = ( Map<String,Object>)apIInfo.get('dataMap');

                List<Map<String,String>> result  = getData(sql,fieldMap,param );
               
                message = Utils.getRestReturnMessage(true,'success',result);

            }else {

                Map<String,Object> sqlMap  = (Map<String,Object>) sqls ;

                Map<String,Object> fieldMaps = ( Map<String,Object>)apIInfo.get('dataMap');

                Map<String,List<Map<String,String> > > res = new Map<String,List<Map<String,String> >>();

                for (String key  : fieldMaps.keySet() ) {

                    String sql = (String) sqlMap.get(key);

                    Map<String,Object> fieldMap = ( Map<String,Object>) fieldMaps.get(key);

                    List<Map<String,String>> result  = getData(sql,fieldMap,param );
                    res.put(key, result);

                }

                message  =Utils.getRestReturnMessage(true, 'success', System.now(), res);
            

            }
           

            
        }catch (Exception e) {
            message = Utils.getRestReturnMessage(false,e.getMessage() ,new List<Map<String ,String>>());

        }

        return message;
        
       
    }
    //解析参数-->重构 sql --> 获取数据 
    global static List<Map<String,String>>  getData(String sql ,Map<String,Object> fieldMap,Map<String,Object> param  ){
            if(System.Test.isRunningTest()) fieldMap.put('Technician__r.Name', 'engineer');
            //获取需要处理的语句块 和 参数
           
            //参数
            Map<String,String> paramMap = new Map<String,String>();
            Pattern paramPattern  = Pattern.compile('(?<=\\{!).*?(?=\\})');
            Matcher m1 = paramPattern.matcher(sql);
            while (m1.find( )) {
                String pName = m1.group(0);
                String pTmp = '{!'+pName +'}';
                paramMap.put(pTmp ,param.containsKey(pName) ? (String)param.get(pName) : '');//System.debug('Found value: ' +  );
            }

            //语句块
            Map<String,String> paramBlock = new Map<String,String>();
            Pattern paramBlockPattern = Pattern.compile('@@.*?##');
            Matcher m = paramBlockPattern.matcher(sql);
            while (m.find()) {
                String blockName = m.group(0);

                String blockResult = '';
                for(String p : paramMap.keyset()){
                    if(blockName.contains(p) && !String.isBlank(paramMap.get(p))){
                        blockResult = blockName.replace('@@', '').replace('##','');
                        break;
                    }

                }
                //System.debug(blockName + '-->'+ blockResult );
                paramBlock.put(blockName, blockResult );
            }
            //重新组装sql
            for (String  blockName : paramBlock.keySet() ) {
                
                sql = sql.replace(blockName, paramBlock.get(blockName));
            }
            for(String pTmp : paramMap.keySet()){

                sql = sql.replace(pTmp, paramMap.get(pTmp));

            }
           System.debug('QueryDataREST==>'+sql);
           List<SObject> res =  Database.query(sql);
           System.debug('QueryDataREST==>'+res);
           List<Map<String,String>> result = new List<Map<String,String>>();
           for (SObject so  : res) {
                Map<String,String> fvMap  = new Map<String,String>();
               for(String field : fieldMap.keyset()){
                    String value = '';
                    if(field.contains('.')){
                        
                        List<String> fcmp= field.split('\\.');

                        SObject val = so;

                        for(Integer j = 0 ; j <fcmp.size() ; j ++){
                            
                            Object tval =  j < fcmp.size() - 1 ? val.getSObject(fcmp.get(j)) : val.get(fcmp.get(j)) ;
                            if(tval == null ) break;
                            if(tval instanceof SObject ){
                                val = (SObject)tval;
                            }else{
                                value = String.valueOf(tval);
                                break;
                            }
                                                    
                        }
                    }else{
                        value = String.valueOf(so.get(field));
                    }
                    fvMap.put((String)fieldMap.get(field), value);

               }
               result.add(fvMap);
           }
        return result;
    }

    global class QueryBean{
        global String method;
        global Map<String,String>params;
    }

   
}

/*

   QueryDataREST.doPost('1134','{"workerno":"2645","name":"1345"}','1134','1134');

   */